#ifndef _SOLVER_TPWT_
#define _SOLVER_TPWT_

//Qt
#include <QtCore/QList>
// Локальные
#include "material.h"
#include "linal/vector.h"
#include "linal/csrmatrix.h"
#include "linal/slaesolver.h"
#include "fem/trianglenet.h"
#include "fem/trianglenetsearch.h"
#include "convection_global.h"

/// Класс, реализующий решение конвективной задачи.
//
/// Решается нестационарная осесимметричная конвективная задача в переменных Температура-Функция тока-Вихрь
/// методом МКЭ с линейными базисными функциями на треугольной сетке.
class CONVECTION_EXPORT SolverTPWt
{
public:
    /// Считывание настроек из файла.
    SolverTPWt();

    /// Освобождение ресурсов.
    virtual ~SolverTPWt(){delete m_NetSearcher;}

    /// Непосредственно решение задачи.
    void solve();

protected:
    /// Возможные состояния процесса кристаллизации.
    //
    /// Если на текущем шаге по времени не обнаружен фронт кристаллизации, то реакция системы зависит от текущего состояния:
    /// если система была в состоянии JastStarted, то считаем, что зародившийся кристалл весь расплавился и система перешла в
    /// состояние NotStarted, а если система была в состоянии InProgress, то считаем, что кристаллизация завершена и система
    /// перешла в состояние Finished.
    enum CrystallizationState
    {
        NotStarted,                 ///< Кристаллизация еще не началась.
        JustStarted,                ///< Кристализация началась только что.
        InProgress,                 ///< Кристаллизация происходит в текущий момент.
        Finished                    ///< Весь расплав закристаллизовался.
    };

    /// Запись результата расчетов в файл.
    void writeResult(int time_layer);

    /// Чтение различной информации о расчетной области и краевых условиях нужной для возобновления расчетов с указанного места.
    void readResumeInfo(int time_layer);

    /// Формирование вектора скорости.
    virtual void formV();

    /// Формирование СЛАУ для температуры.
    void formTSLAE(int time_layer);

    /// Формирование СЛАУ для функции тока.
    void formPsiSLAE(int time_layer);

    /// Формирование СЛАУ для вихря.
    void formOmegaSLAE(int time_layer);

    /// Учет краевых условий для температуры.
    void tBC(int time_layer);

    /// Учет краевых условий для функции тока.
    void psiBC(int time_layer);

    /// Учет краевых условий для вихря.
    void omegaBC(int time_layer);

    /// Решение СЛАУ.
    //
    /// Идет последовательный перебор различных методов решения СЛАУ до тех пор, пока решение не будет найдено.
    bool solveSLAE(const linal::CSRMatrix &A, const linal::Vector &f, linal::Vector &x);

    /// Перестройка сетки с учетом продвижения фронта.
    virtual bool recreateNet() = 0;

    //****************************************************************************************************************************
    //Физические и геометрические параметры задачи.
    //****************************************************************************************************************************
    QList<Material> m_Materials;    ///< Список материалов расчетной области.
    double m_TCrystal;              ///< Температура кристаллизации расплава.
    double m_TGrad;                 ///< Градиент температуры в печи.
    double m_TMax;                  ///< Температура в горячей зоне печи.
    double m_TRod;                  ///< Температура державки.
    double m_V;                     ///< Скорость опускания тигля.

    //****************************************************************************************************************************
    // Математические параметры задачи.
    //****************************************************************************************************************************
    int m_MaxiterSLAE;              ///< Максимальное число итераций, отведенное на решение СЛАУ.
    int m_MaxiterNonlin;            ///< Максимальное число итераций, отведенное на решение нелинейной задачи.
    double m_EpsSLAE;               ///< Невязка, достаточная для того, чтобы объявить решение СЛАУ найденным.
    double m_EpsNonlin;             ///< Невязка, достаточная для того, чтобы объявить решение нелинейной задачи найденным.
    double m_DiffStep;              ///< Шаг, используемый для численного нахождения производных.
    double m_FrontHalfWidth;        ///< Полуширина фронта кристаллизации(в градусах).
    double m_MinCrystalHeight;      ///< Минимальная высота кристалла.
    double m_W;                     ///< Коэффициент релаксации.
    QList<linal::SLAESolver*> m_Solvers;    ///< Список решателей СЛАУ.

    //****************************************************************************************************************************
    // Пространственная сетка.
    //****************************************************************************************************************************
    fem::TriangleNet m_Net;         ///< Конечноэлементная сетка.
    fem::TriangleNetSearch *m_NetSearcher;  ///< Класс, обеспечивающий поиск по конечноэлементной сетке.

    //****************************************************************************************************************************
    // Временная сетка.
    //****************************************************************************************************************************
    double m_TimeStep;              ///< Шаг по времени.
    int m_NumOfTimeLayers;          ///< Число шагов по времени.

    //****************************************************************************************************************************
    // Значения искомых функций в узлах сетки
    //****************************************************************************************************************************
    linal::Vector m_T;              ///< Значение температуры.
    linal::Vector m_Psi;            ///< Значение функции тока.
    linal::Vector m_Omega;          ///< Значение вихря.
    linal::Vector m_Vr;             ///< Значение радиальной компоненты скорости конвективного течения.
    linal::Vector m_Vz;             ///< Значение осевой компоненты скорости конвективного течения.

    linal::Vector m_TOldNolin;      ///< Значение температуры с предыдущей итерации по нелинейности.
    linal::Vector m_PsiOldNolin;    ///< Значение функции тока с предыдущей итерации по нелинейности.
    linal::Vector m_OmegaOldNolin;  ///< Значение вихря с предыдущей итерации по нелинейности.

    linal::Vector m_TOldTime;       ///< Значение температуры с предыдущей итерации по времени.
    linal::Vector m_OmegaOldTime;   ///< Значение вихря с предыдущей итерации по времени.

    //****************************************************************************************************************************
    // Краевые условия.
    //****************************************************************************************************************************
    QList<int> m_TopTBC;            ///< Номера узлов конечноэлементной сетки, в которых задано КУ первого рода для температуры.
    QList<int> m_TypeTBC;           ///< Номера формул, по которым выисляеются значения КУ первого рода в соответствующих узлах сетки.
    QList<int> m_TopPsiBC;          ///< Номера узлов конечноэлементной сетки, в которых задано КУ первого рада для функции тока.
    QList<int> m_TypePsiBC;         ///< Номера формул, по которым выисляеются значения КУ первого рода в соответствующих узлах сетки.
    QList<int> m_TopOmegaBC;        ///< Номера узлов конечноэлементной сетки, в которых задано КУ первого рада для функции вихря.
    QList<int> m_TypeOmegaBC;       ///< Номера формул, по которым выисляеются значения КУ первого рода в соответствующих узлах сетки.

    //****************************************************************************************************************************
    // Фронт кристаллизации.
    //****************************************************************************************************************************
    QList<int> m_Front;             ///< Фронт с текущей итерации. Хранится в виде индексов точек конечноэлементной сетки.
    CrystallizationState m_State;   ///< Состояние процесса кристаллизации.

    //****************************************************************************************************************************
    // Матрица и вектор правой части СЛАУ
    //****************************************************************************************************************************
    linal::CSRMatrix m_A;           ///< Матрица СЛАУ.
    linal::Vector m_F;              ///< Вектор правой части.

    //****************************************************************************************************************************
    // Сервисные настройки(настройки не связанные непосредственно с процессом моделирования).
    //****************************************************************************************************************************
    int m_OutputStep;               ///< Переодичность вывода результатов (в итерациях).
    QString m_OutputPath;           ///< Директория для записи результатов.
};

#endif // _SOLVER_TPWT_
